package com.caption.api.handler.manager;

import com.caption.api.entity.FaceAuthCondition;
import com.caption.api.entity.IDCarAuthCondition;
import com.caption.api.handler.base.AbstractHandler;
import com.caption.api.handler.impl.FaceAuthHandler;
import com.caption.api.handler.impl.IDCardAuthHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

/**
 * 请求分发管理器
 */
@Component
@Slf4j
public class ApiHandlerManager {
    private ThreadLocal<AbstractHandler> threadLocal = new ThreadLocal<>();

    public <T> void setHandler(T condition, String version) throws Exception {
        setHandler(condition);
        setHandler(version);
    }

    /**
     * 设置请求版本号
     *
     * @param version
     */
    private void setHandler(String version) {
        threadLocal.get().setVersion(version);
    }

    /**
     * 设置请求条件
     *
     * @param condition
     * @param <T>
     */
    private  <T> void setHandler(T condition) throws Exception {
        AbstractHandler handler = null;
        if (condition instanceof IDCarAuthCondition) {
            handler = new IDCardAuthHandler((IDCarAuthCondition) condition);
        } else if (condition instanceof FaceAuthCondition) {
            handler = new FaceAuthHandler((FaceAuthCondition) condition);
        } else {
            throw new RuntimeException("条件没有对于处理器");
        }
        threadLocal.set(handler);
    }

    /**
     * 执行调用业务代码，注意必须要调用clear方法，后期可以封装异常统一处理
     *
     * @param <T>
     * @return
     */
    public <T> T call() {
        T t = null;
        try {
            t = threadLocal.get().call();
        } catch (ExecutionException e) {
            log.info("执行业务代码出现异常");
        } catch (InterruptedException e) {
            log.info("线程中断异常");
        } catch (TimeoutException e) {
            log.info("请求超时异常");
        }
        clear();
        return t;
    }


    /**
     * 调用threadLocal.remove 防止内存泄露
     */
    private void clear() {
        threadLocal.remove();
    }


}
